package com.java.linkedlist;

/**
 * 双向链表
 */
public class DoubleLinkedListDemo {

    public static void main(String[] args) {

        System.out.println("双向链表的测试");

        //先创建节点
        HeroNode2 heroNode = new HeroNode2(1, "dc", "we");
        HeroNode2 heroNode1 = new HeroNode2(2, "ch", "eat");
        HeroNode2 heroNode2 = new HeroNode2(3, "lh", "sing");
        HeroNode2 heroNode3 = new HeroNode2(4, "hk", "study");

        //创建链表
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();

        //将节点添加到链表中
        doubleLinkedList.add(heroNode);
        doubleLinkedList.add(heroNode1);
        doubleLinkedList.add(heroNode2);
        doubleLinkedList.add(heroNode3);
        doubleLinkedList.list();

        System.out.println("修改后的链表");
        HeroNode2 heroNode4 = new HeroNode2(4, "ab", "study");
        doubleLinkedList.update(heroNode4);
        doubleLinkedList.list();

        System.out.println("删除节点");
        doubleLinkedList.delete(4);
        doubleLinkedList.list();



    }
}

class DoubleLinkedList{

    //先初始化一个 头节点，头节点不动 , 不存放具体的数据
    private HeroNode2 head = new HeroNode2(0,"","");


    //头节点
    public HeroNode2 getHead() {
        return head;
    }

    //遍历双向链表
    /**
     * 显示链表中的全部数据信息
     */
    public void list(){
        //先判断链表是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //因为头节点，不能动 ， 因此我们需要一个辅助遍历来遍历
        HeroNode2 temp = head.next;
        while (true){
            //判断是否是链表的最后
            if (temp == null){
                break;
            }
            //输出节点的信息
            System.out.println(temp);
            //将temp后移，一定要后移，否则会死循环
            temp = temp.next;
        }
    }



    //双向链表添加：添加一个节点到双向链表的最后
    public void add(HeroNode2 heroNode){

        //因为 head不动 ，因此我们小一个辅助遍历 temp
        HeroNode2 temp = head;
        //遍历链表找到最后
        while (true){
            //当
            if (temp.next == null){
                break;
            }
            //如果没有找到最后 , 就将temp后移
            temp = temp.next;
        }
        //当退出while循环时， temp 就指向了链表的最后
        temp.next = heroNode;
        heroNode.pre = temp; //形成一个双向链表
    }

    /**
     * 按编号添加，按顺序添加
     */


    //修改节点内容：双向和单向修改一样
    public void update(HeroNode2 newHeroNoe){
        //判断是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //找到需要修改的节点 ， 根据 no 编号
        //先定义一个辅助变量
        HeroNode2 temp = head.next;
        boolean flag = false; //表示没找打到该节点
        while (true){
            if (temp == null){
                break; //到链表的最后，没有找到要修改的节点
            }
            if (temp.no == newHeroNoe.no){ //找到了
                flag = true;
                break;
            }
            temp = temp.next;
        }

        //根据flag判断是否找到
        if (flag){
            //找到了，修改
            temp.name = newHeroNoe.name;
            temp.nickName = newHeroNoe.nickName;
        }else {
            //没有找到
            System.out.println("没有找到该编号的节点，不能修改:"+newHeroNoe.no);
        }

    }

    //从双向链表删除一个节点
    //双向链表可以直接找到这个节点，找到后可以自己删除
    //
    public void delete(int no){

        //判断当前链表是否为空
        if (head.next == null){
            System.out.println("链表为空，无法删除");
            return;
        }

        HeroNode2 temp = head.next;//辅助变量
        boolean flag = false;//表示没有找到删除节点的前一个节点
        while (true){
            if (temp == null){ //没有找到要删除的节点,找到了链表的最后
                break;
            }
            if (temp.no == no){
                flag = true; //找到了
                break;
            }
            temp = temp.next;//后移
        }

        //判断flag
        if (flag){
            //找到，可以删除
//            temp.next = temp.next.next; //但链表的删除方式
            temp.pre.next = temp.next; //将
            //如果是最后一个节点就不需要执行这句话，否则会有空指针异常
            if (temp.next != null) {
                temp.next.pre = temp.pre;//将要删除节点的 next和pre 都去掉（但如果是最后一个，最后一个后面没有节点了）
            }
        }else {
            System.out.println("没有找到要删除的节点，该节点不存在："+no);
        }
    }


}


class HeroNode2{

    public int no;
    public String name;
    public String nickName;
    public HeroNode2 next; //指向下一个节点 默认null
    public HeroNode2 pre;//指向前一个节点，默认null

    public HeroNode2 getNext() {
        return next;
    }

    public HeroNode2 getPre(){
        return pre;
    }

    private static final String  a = null;

    public HeroNode2(int no, String name, String nickName){
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }

    //为了显示方法，重写toString方法
    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName  +
                '}';
    }


}